package com.hulman.oms.service;

import com.hulman.oms.bean.*;
import com.hulman.oms.dao.DeviceDao;
import com.hulman.oms.exception.IoTException;
import com.hulman.oms.util.CodeGenerator;
import com.hulman.oms.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: maxwellens
 */
@Service
public class DeviceService
{
    @Autowired
    private DeviceDao deviceDao;
    @Autowired
    private TunnelService tunnelService;
    @Autowired
    private LocationService locationService;
    @Autowired
    private DeviceTypeService deviceTypeService;
    @Autowired
    private DeviceSystemService deviceSystemService;
    @Autowired
    private DeviceRelationService deviceRelationService;
    @Autowired
    private AccessoryService accessoryService;
    @Autowired
    private IotDeviceService iotDeviceService;

    public List<Device> findDevices(Map<String, Object> map)
    {
        return deviceDao.findDevices(map);
    }

    public List<Device> findDevicesByTunnelIdAndSystem(Integer tunnelId, String system)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("tunnelId", tunnelId);
        map.put("system", system);
        return findDevices(map);
    }

    public List<Device> findDevicesBySystem(String system)
    {
        return deviceDao.findDevicesBySystem(system);
    }

    public List<Device> findAllDevices()
    {
        Map<String, Object> map = new HashMap<>();
        return deviceDao.findDevices(map);
    }

    public List<Device> findDevicesByProjectId(Integer projectId)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("projectId", projectId);
        return deviceDao.findDevices(map);
    }

    public Integer findDevicesCount(Map<String, Object> map)
    {
        return deviceDao.findDevicesCount(map);
    }

    public Result findDevicesResult(Map<String, Object> map)
    {
        Integer page = (Integer) map.get("page");
        Integer limit = (Integer) map.get("limit");
        if (page != null && limit != null)
        {
            map.put("start", (page - 1) * limit);
            map.put("length", limit);
        }
        int count = deviceDao.findDevicesCount(map);
        List<Device> data = deviceDao.findDevices(map);
        return new Result(data, count);
    }

    public Device findDeviceById(Integer id)
    {
        return deviceDao.findDeviceById(id);
    }

    public Device findDeviceByCode(String code)
    {
        return deviceDao.findDeviceByCode(code);
    }

    public Device findDeviceByName(String name)
    {
        return deviceDao.findDeviceByName(name);
    }

    public Device findDeviceByTunnelAndName(String tunnelName, String deviceName) throws IoTException
    {
        Tunnel tunnel = tunnelService.findTunnelByName(tunnelName);
        if (tunnel == null)
        {
            throw new IoTException("不存在隧道名称：" + tunnelName);
        }
        Device device = deviceDao.findDeviceByTunnelIdAndName(tunnel.getId(), deviceName);
        return device;
    }

    public void saveDevice(Device device)
    {
        if (StringUtil.isEmpty(device.getCode()))
        {
            device.setCode(CodeGenerator.nextCode());
        }
        if (device.getId() != null && device.getId() != 0)
        {
            deviceDao.updateDevice(device);
        } else
        {
            //默认运行状态
            device.setState(1);
            device.setMaintainTimes(0);
            deviceDao.insertDevice(device);
        }
    }

    public void deleteDeviceById(Integer id)
    {
        deviceDao.deleteDeviceById(id);
    }

    public void deleteDevices(int[] ids)
    {
        deviceDao.deleteDevices(ids);
    }

    public List<Device> findDevicesByIds(int[] ids)
    {
        return deviceDao.findDevicesByIds(ids);
    }

    @Transactional(rollbackFor = Exception.class)
    public void importDevices(List<Device> devices, List<Accessory> accessories, List<IotDevice> iotDevices) throws IOException
    {
        //导入设备
        for (Device device : devices)
        {
            importDevice(device);
        }
        //添加关联设备
        for (Device device : devices)
        {
            deviceRelationService.importDeviceRelations(device);
        }
        //导入附件
        /*for (Accessory accessory : accessories)
        {
            accessoryService.importAccessory(accessory);
        }*/
        //导入相关物联设备
        for (IotDevice iotDevice : iotDevices)
        {
            iotDeviceService.importIotDevice(iotDevice);
        }
    }

    public void importDevice(Device device)
    {
        //名称转ID
        Tunnel tunnel = tunnelService.findTunnelByName(device.getTunnelName());
        if (tunnel != null)
        {
            device.setTunnelId(tunnel.getId());
        } else
        {
            throw new IoTException("不存在隧道：" + device.getTunnelName());
        }
        //同时支持位置名称和别名
        Location location = locationService.findLocationByName(device.getLocationName());
        if (location == null)
        {
            location = locationService.findLocationByTunnelIdAndAbbr(tunnel.getId(), device.getLocationName());
        }
        if (location != null)
        {
            device.setLocationId(location.getId());
        } else
        {
            throw new IoTException("不存在位置：" + device.getLocationName());
        }
        //检查设备类型
        if (!StringUtil.isEmpty(device.getType()))
        {
            deviceTypeService.checkAndSave(device.getType());
        }
        //检查设备系统
        DeviceSystem deviceSystem = deviceSystemService.findDeviceSystemByName(device.getSystem());
        if (deviceSystem == null)
        {
            throw new IoTException("不存在设备系统：" + device.getSystem());
        }
        //存在设备编码则更新设备信息
        Device dev = deviceDao.findDeviceByCode(device.getCode());
        if (dev != null)
        {
            device.setId(dev.getId());
        }
        saveDevice(device);
    }

    public Device findDeviceByIotCode(String iotCode)
    {
        return deviceDao.findDeviceByIotCode(iotCode);
    }

    public List<NameValue> statSystemCount()
    {
        return deviceDao.statSystemCount();
    }

    /**
     * 更新运维信息（运维次数+1，更新最近运维时间）
     *
     * @param deviceId 设备ID
     */
    public void refreshMaintainInfo(Integer deviceId)
    {
        deviceDao.refreshMaintainInfo(deviceId);
    }
}
